<?php

namespace PhpYes\Apps;

use PhpYes\Yes;

/**
 * 通用说明:
 *
 * 1. 本类中 没有使用 final 修饰的 public 和 protected 成员方法 都是 子类可以重写的.
 *
 */
abstract class BaseAppBase
{
    const ENV_PRODUCTION = 'production';
    const ENV_DEVELOP = 'develop';
    const ENV_TEST = 'test';

    const KEY_BASE_DIR = 'base_dir';
    const KEY_BUILD_TIME = 'build_time';

    /**
     * @return string
     */
    abstract public function base_dir();

    /**
     * 主项目 : = self.base_dir()
     * 子项目 : = self.base_dir() . '/SubProjectDir'
     * @return string
     */
    abstract public function home_dir();

    /**
     * @return string
     */
    public function assets_dir()
    {
        return $this->base_dir() . '/assets';
    }

    /**
     * @return string
     */
    public function bin_dir()
    {
        return $this->base_dir() . '/bin';
    }

    /**
     * @return string
     */
    public function config_dir()
    {
        return $this->base_dir() . '/config';
    }

    /**
     * @return string - libs 将会被安装进的目录
     */
    public function libs_dir()
    {
        return $this->base_dir() . '/libs';
    }

    /**
     * @return string
     */
    public function public_dir()
    {
        return $this->base_dir() . '/public';
    }

    /**
     * @return string
     */
    public function var_dir()
    {
        return $this->base_dir() . '/var';
    }

    /**
     * @return string
     */
    abstract public function env();

    /**
     * build_time 文件虽然放在 config 目录中，但却是一个项目属性，
     * 所以不用遵循 config 惯例(例如函数名是 config_build_time_file(), 并且 return 'build_time'),
     *
     * 我们希望就算把 build_time 文件放在 config 目录之外的地方，
     * 我们也不用改变 build_time 函数的逻辑，只需要改变 build_time_file 函数的返回值就可以了，
     * 这也要求 build_time_file 不能只 return 'build_time', 而应该 return 一个绝对路径，
     * 这也要求 build_time_file 不能遵循 config 惯例
     * @return string
     */
    public function build_time_file()
    {
        return $this->config_dir() . '/build_time';
    }

    /**
     * @return int - 获取项目的构建时间
     */
    public function build_time()
    {
        if (isset(Yes::$kv[self::KEY_BUILD_TIME]) && Yes::$kv[self::KEY_BUILD_TIME] > 0) {
            return Yes::$kv[self::KEY_BUILD_TIME];
        }

        $file = $this->build_time_file();
        if (!is_file($file)) {
            Yes::$kv[self::KEY_BUILD_TIME] = time();
            return Yes::$kv[self::KEY_BUILD_TIME];
        }

        $time = file_get_contents($file);
        $time = empty($time) ? 0 : intval($time);
        if ($time < 1) {
            $time = time();
        }
        Yes::$kv[self::KEY_BUILD_TIME] = $time;
        return $time;
    }
}